package com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.MathUtil;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.graphics.renderIt.api.renderItGraphicsInterface;
import com.nulldev.util.graphics.renderIt.api.envcaps.renderItOperations;
import com.nulldev.util.graphics.renderIt.util.renderPosition;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.web.HttpClient.HttpClient;
import com.nulldev.util.web.flexibleKit.flexRenderer.FlexEnvironment;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.PathGenerator;
import com.nulldev.util.web.flexibleKit.general.RenderOperation;
import com.nulldev.util.web.flexibleKit.general.flexKit;
import com.nulldev.util.web.flexibleKit.jfvParse.Element;
import com.nulldev.util.web.flexibleKit.jfvParse.Node;

public class ImageGenerator implements PathGenerator {

	private static final Logger LOG = LoggerFactory.getLogger();

	@Override
	public RenderOperation generate(final Node n, final PathGenerationFlags... flags) {
		final RenderOperation ri = new RenderOperation() {

			@Override
			public renderPosition doRender(renderItGraphicsInterface i, final renderPosition rp, final FlexEnvironment env) {
				if (i.supportsOperations(renderItOperations.RIT_SWING_image_draw)) {
					String src = ((Element) n).getAttribute("src");
					if (src != null && src.startsWith("/") && !src.startsWith("//")) {
						if (env.domain != null) {
							LOG.debug("Using domain: " + env.domain);
							LOG.debug("src: " + src);
							src = "https://" + env.domain + src;
						} else {
							LOG.warn("No domain found, skipping image.");
							src = null;
						}
					} else if (src != null && src.startsWith("//")) {
						LOG.debug("Generalized url found, appending HTTPS.");
						src = "https:" + src;
					} else {
						LOG.dwarn("Unknown Image URL: " + src);
					}
					if (src != null) {
						BufferedImage bi;
						LOG.info("imgCache: " + env.imgCache);
						if (env.imgCache.has(n.hashCode())) {
							bi = env.imgCache.get(n.hashCode());
						} else {
							try {
								if (src.startsWith("data:")) {
									LOG.error("Unsupported image type: " + src);
									bi = null;
								} else {
									bi = ImageIO.read(HttpClient.getStream().url(src).forceHeader("User-Agent", flexKit.getUserAgent()).create().data());
									env.imgCache.put(n.hashCode(), bi);
								}
							} catch (Exception e) {
								LOG.error("Failed to load image: " + src, e);
								bi = null;
							}
						}
						if (bi != null) {
							int width = -1;
							if (((Element) n).hasAttribute("width")) {
								final String w = ((Element) n).getAttribute("width");
								if (StringsUtil.isNumber(w)) {
									width = MathUtil.safeParseInt(w, -1);
								} else
									LOG.warn("Unknown width: " + w);
							}
							int height = -1;
							if (((Element) n).hasAttribute("height")) {
								final String h = ((Element) n).getAttribute("height");
								if (StringsUtil.isNumber(h)) {
									height = MathUtil.safeParseInt(h, -1);
								} else
									LOG.warn("Unknown height: " + h);
							}
							i.swing_drawImage(bi, rp.getX(), rp.getY(), width < 0 ? bi.getWidth() : width, height < 0 ? bi.getHeight() : height);
							if (ArrayUtils.contains(flags, PathGenerationFlags.RENDER_INLINE)) {
								rp.addX(width < 0 ? bi.getWidth() : width);
							} else {
								rp.addY(15);
								rp.resetX();
							}
							rp.addY(height < 0 ? bi.getHeight() : height);
//							i.runQuirkFix(RenderingQuirks.RESET_X_AFTER_CALL, null);
							return rp.clone().addX(width < 0 ? bi.getWidth() : width);
						}
						rp.addY(10);
					}
				} else
					LOG.error("renderIt! Environment does not support RIT_SWING_image_draw!");
				return rp;
			}

			@Override
			public Node operationFor() {
				return n;
			}

			@Override
			public boolean keepInline() {
				return ArrayUtils.contains(flags, PathGenerationFlags.RENDER_INLINE);
			}
		};
		return ri;
	}

}
